package com.xunk.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xunk.common.core.domain.ControlDeviceParam;
import com.xunk.common.core.web.domain.AjaxResult;
import com.xunk.common.redis.service.RedisService;
import com.xunk.equipment.api.RemoteEquipmentService;
import com.xunk.system.domain.SysDevice;
import com.xunk.system.domain.SysScene;
import com.xunk.system.domain.SysSceneDevice;
import com.xunk.system.domain.SysSceneHome;
import com.xunk.system.mapper.SysDeviceMapper;
import com.xunk.system.mapper.SysHomeMapper;
import com.xunk.system.mapper.SysSceneMapper;
import com.xunk.system.service.ISysSceneService;
import com.xunk.system.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ProjectName: xunk
 * @Package: com.xunk.buz.service.impl
 * @ClassName: ISysSceneServiceimpl
 * @Author: dongxiaoxin
 * @Description: 规定场景实现类
 * @Date: 2021/4/6 14:44
 * @Version: 1.0
 */
@Slf4j
@Service
public class ISysSceneServiceimpl implements ISysSceneService {

    @Autowired
    RemoteEquipmentService service;

    @Autowired
    SysHomeMapper mapper;

    @Autowired
    SysSceneMapper sceneMapper;

    @Autowired
    SysDeviceMapper deviceMapper;

    @Autowired
    RedisService redisService;

    private static final String PERFORM_STATUS = "0";

    private static final List<String> FIX_SCENE_INDEX = Arrays.asList("backHome,leaveHome,morning,evening".split(","));

    @Override
    public void saveOrUpdateHomeScene(FixSceneVo fixSceneVo) {

        Long homeId = fixSceneVo.getHomeId();
        Long sceneId = sceneMapper.selectSceneIdByCode(fixSceneVo.getCode());
        Integer status = sceneMapper.selectSceneStatus(homeId, sceneId);
        if (status == null){
            SysSceneHome sysSceneHome = new SysSceneHome();
            sysSceneHome.setHomeId(homeId);
            sysSceneHome.setSceneId(sceneId);
            sysSceneHome.setStatus(1);
            sysSceneHome.setIndexFlag(1);
            sceneMapper.insertSysSceneHome(sysSceneHome);
        }else {
            sceneMapper.updateSceneHomeInfo(sceneId,"1",homeId);
        }
        for (EquipmentVO param : fixSceneVo.getList()) {

            Long aLong = sceneMapper.checkSceneDevice(param.getDeviceSn(), param.getActionCmd(), sceneId);
            if (aLong > 0){

                //  更新对应的状态
                sceneMapper.updateSceneHome(param.getDeviceSn(),param.getActionCmd(),sceneId,param.getStatus());
            }else {

                SysDevice sysDevice = deviceMapper.selectSysDeviceById(param.getDeviceSn());
                SysScene scene = sceneMapper.selectSysSceneByCode(fixSceneVo.getCode());
                List<SysSceneType> sysSceneTypes = JSONObject.parseArray(scene.getSceneFunction(), SysSceneType.class);
                String descirbe = "",functionName = "",actionCmd = "";
                for (SysSceneType sysSceneType : sysSceneTypes) {
                    if (sysSceneType.getType().equals(param.getActionCmd()) && sysDevice.getDeviceType().equals(sysSceneType.getDeviceType())){
                        descirbe = sysSceneType.getName();
                        functionName = sysSceneType.getAction();
                        actionCmd = sysSceneType.getValue();
                    }
                }
                SysSceneDevice sceneDevice = new SysSceneDevice();
                sceneDevice.setSceneId(sceneId);
                sceneDevice.setDeviceSn(param.getDeviceSn());
                sceneDevice.setActionCmd(actionCmd);
                sceneDevice.setFunctionCmd(param.getActionCmd());
                sceneDevice.setFunctionName(functionName);
                sceneDevice.setStatus(param.getStatus());
                sceneDevice.setDescribe(descirbe);
                sceneMapper.insertSysSceneDevice(sceneDevice);
            }
        }

    }

    @Override
    public AjaxResult controlFixScene(FixSceneVo fixSceneVo) {

        log.info("method:{},params:{}","controlFixScene",JSONObject.toJSONString(fixSceneVo));
        Long sceneId = sceneMapper.selectSceneIdByCode(fixSceneVo.getCode());

        this.saveOrUpdateHomeScene(fixSceneVo);

        List<ControlDeviceParam> params = new ArrayList<>();
        for (EquipmentVO param : fixSceneVo.getList()) {
            if (PERFORM_STATUS.equals(param.getStatus())){
                params.add(sceneMapper.selectDeviceControlParam(param.getDeviceSn(),param.getActionCmd(),sceneId));
            }
        }
        AjaxResult result = service.controlDevice(params);
        if (!result.isSuccess()){
            List<ControlDeviceParam> errorList = JSONObject.parseArray(JSONObject.toJSONString(result.getData()), ControlDeviceParam.class);
            log.info("操作失败设备列表：{}",JSONObject.toJSONString(errorList));
            StringBuilder errMsg = new StringBuilder();
            for (ControlDeviceParam controlDeviceParam : errorList) {
                String deviceName = controlDeviceParam.getDeviceName();
                errMsg.append(deviceName).append(",");
            }
            return AjaxResult.error(errMsg.substring(0, errMsg.length() - 1) + "调整失败");
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult performSceneNow(String code, Long homeId) {
        return this.controlFixScene(new FixSceneVo(homeId,code,this.getDeviceList(homeId,code)));
    }

    @Override
    public List<EquipmentVO> getDeviceList(Long homeId, String mode) {

        List<SysDeviceBaseVO> devices = deviceMapper.selectDeviceInfoByHomeId(null, homeId);
        SysScene scene = sceneMapper.selectSysSceneByCode(mode);

        List<EquipmentVO> list = new ArrayList<>();

        List<SysSceneType> sysSceneTypes = JSONObject.parseArray(scene.getSceneFunction(), SysSceneType.class);

        for (SysSceneType type : sysSceneTypes) {
            String deviceType = type.getDeviceType();
            String supplier = type.getSupplier();
            for (SysDeviceBaseVO device : devices) {
                if (deviceType.equals(device.getDeviceType()) && supplier.equals(device.getSupplier())){
                    list.add(new EquipmentVO(type.getName(),type.getAction(),type.getType(),device.getDeviceSn(),device.getDeviceName(),
                            PERFORM_STATUS.equals(device.getOnline()) ? "1" : "0",deviceType,device.getOnline()));
                }
            }
        }

        List<EquipmentVO> vos = mapper.selectDeviceByScene(homeId, mode);
        list.removeIf(vos::contains);
        vos.addAll(list);
        return vos;
    }

    @Override
    public List<FixSceneInfoVO> getSceneList(Long homeId, String position) {

        return sceneMapper.selectSceneByHomeId(homeId,position);
    }

    @Override
    public void updateScenePosition(String code, Long homeId, Integer flag) {

        Long sceneId = sceneMapper.selectSceneIdByCode(code);
        sceneMapper.updateScenePosition(sceneId,homeId,flag);
    }

    @Override
    public void insertSysSceneHome(Long homeId) {

        List<SysScene> sysScenes = sceneMapper.selectSysSceneList(new SysScene());

        List<SysSceneHome> scenes = sysScenes.parallelStream().map(scene -> {

            SysSceneHome sysSceneHome = new SysSceneHome();
            sysSceneHome.setHomeId(homeId);
            sysSceneHome.setSceneId(scene.getSceneId());
            sysSceneHome.setStatus(1);
            sysSceneHome.setIndexFlag(FIX_SCENE_INDEX.contains(scene.getCode()) ? 1 : 0);
            return sysSceneHome;
        }).collect(Collectors.toList());
        sceneMapper.insertSysSceneHomeList(scenes);
    }

    @Override
    @Transactional
    public void saveSceneDetail(FixSceneVo fixSceneVo) {

        updateScenePosition(fixSceneVo.getCode(),fixSceneVo.getHomeId(),1);
        saveOrUpdateHomeScene(fixSceneVo);
    }
}
